#ifndef POST_DATA_H
#define POST_DATA_H

#include <vector>
#include <string>
#include "DataBase.h"
#include "vtkTable.h"
#include "vtkPoints.h"
#include "vtkLine.h"
#include "vtkCellArray.h"
#include "vtkSmartPointer.h"
#include "vtkPolyDataMapper.h"

constexpr float PI = 3.141592653;

struct Complex {
    float re{ 0 };
    float im{ 0 };
};

struct FarPara {
    std::string sName;
    std::vector<float> vPhi;
    std::vector<float> vTheta;
};

struct DataFar {
    std::vector<Complex> vEt;
    std::vector<Complex> vEp;
    std::vector<float> vAbsE;
    std::vector<float> vGain;
    std::vector<float> vDire;
};

struct FarSurf {
    std::vector<DataFar> vFreqFar;
};

struct OneFar {
    bool bHasLoad{ false };
    std::vector<FarSurf> vSurfData;
};

struct DataEH {
    std::vector<Complex> vEx;
    std::vector<Complex> vEy;
    std::vector<Complex> vEz;
    std::vector<Complex> vHx;
    std::vector<Complex> vHy;
    std::vector<Complex> vHz;
};

struct NearSurf {
    std::string sName;
    std::vector<DataEH> vFreqNear;
};

struct OneNear {
    bool bHasLoad{ false };
    std::vector<NearSurf> vSurfData;
};

struct OneCurr {
    bool bHasLoad{ false };
    std::vector<DataEH> vFreqCur;
};

struct DataNet {
    bool bHasLoad{ false };
    int iNumPort{ 0 };
    std::string sFreqUnit;
    std::vector<float> vFreq;
    std::vector<std::vector<Complex>> vS;
    std::vector<std::vector<Complex>> vY;
    std::vector<std::vector<Complex>> vZ;
};

struct FarSet {
    bool bCancel{ false };
    bool bGrf2D{ true };
    bool bTheta{ true };        // x-axial for 2D photo
    bool bNormlize{ true };     // is normalize
    bool bSetdB{ true };        // is dB
    int iVoltIdx{ 0 };
    int iFrqIndx{ 0 };          // frequency index
	int iFarIndx{ 0 };          // far surface index
	QString sQuantity;          // Electric, RCS, Gain, Directivtiy, Axial
    QString sComponent;         // Total, Theta, Phi
    QString sPart;              // Real, Image, Mag, Phase
	int iCoordinate;
    std::vector<int> vAngleIndx;
};

struct NearSet {
    bool bCancel{ false };
    bool bIsE{ true };
    bool bNormlize{ true };     // is normalize
    bool bSetdB{ true };        // is dB
    int iVoltIndx{ 0 };
    int iFreqIndx{ 0 };         // frequency index
    std::vector<int> vNearIndx; // near surface index
    QString sComponent;         // Total, Theta, Phi
    QString sPart;              // Real, Image, Mag, Phase
};

struct CurSet {
    bool bCancel{ false };
    bool bIsJ{ true };
    bool bNormlize{ true };     // is normalize
    bool bSetdB{ true };        // is dB
    int iVoltIndx{ 0 };
    int iFreqIndx{ 0 };         // frequency index
    QString sComponent;         // Total, Theta, Phi
    QString sPart;              // Real, Image, Mag, Phase
};

struct NetSet {
    bool bCancel{ false };
    std::string sType;
    std::vector<std::string> vLabel;
    std::vector<int> vPart;     // Real, Image, Mag, Phase
    std::vector<int> vPortI;
    std::vector<int> vPortJ;
};

struct CurMsh {
    bool bHasLoad{ false };
    std::vector<Node> vR;
    std::vector<std::vector<int>> vvWire;
    std::vector<std::vector<int>> vvTria;
    std::vector<std::vector<int>> vvQuad;
};

class PostData
{
public:
    PostData() = default;
    ~PostData() {}

    int m_iNumVolt{ 0 };
    bool m_bRCS{ false };
    bool m_bNet{ false };
    std::vector<float> m_vFreq;
    std::vector<FarPara> m_vFarPara;
    std::vector<std::string> m_vNearName;
    CurMsh m_cmsh;
    
    std::vector<OneFar> m_vFar;
    std::vector<OneNear> m_vNear;
    std::vector<OneCurr> m_vCurr;
    DataNet m_Net;

    bool fn_LoadOneFar(std::string &sPostFile, int &iVolt);
    bool fn_LoadOneNear(std::string &sPostFile, int &iVolt);
    bool fn_LoadOneCurr(std::string &sPostFile, int &iVolt);
    bool fn_LoadNetPara(std::string &sPostFile);
    bool fn_LoadCurrMsh(std::string &sPostFile);
    void fn_ClearData();
    void fn_SetPostData(DataBase &data);
    vtkSmartPointer<vtkPolyDataMapper> fn_CreateMapper(FarSet &para, Node &Oc, float rad, float range);
    vtkSmartPointer<vtkPolyDataMapper> fn_CreateMapper(NearSet&para, DataBase &data, float range);
    vtkSmartPointer<vtkPolyDataMapper> fn_CreateMapper(CurSet &para, DataBase &data, float range);
    vtkSmartPointer<vtkTable> fn_CreateTable(FarSet &para, std::string &xLabel, std::string &yLabel);
    vtkSmartPointer<vtkTable> fn_CreateTable(NetSet &para, std::string &xLabel, std::string &yLabel);

private:
    void fn_GetFarValue(FarSet &para, DataFar *far, std::vector<float> &vValue);
    void fn_GetCurveFar(FarSet &para, DataFar *far, float **val);
    void fn_GetNfcValue(bool &bE, QString &sComponent, QString &sPart, DataEH *near, std::vector<float> &vValue);
    void fn_SetNearMesh(PreNearSet &near, vtkIdType &n, vtkPoints *pnt, vtkCellArray *line, vtkCellArray *poly);
    float fn_GetAxial(Complex &Et, Complex &Ep);
};

float fn_GetPhase(float &re, float &im);

#endif
